package com.ruyuan.dfs.namenode.editslog;

import com.ruyuan.dfs.namenode.config.NameNodeConfig;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.List;

/**
 * 双缓冲机制
 *
 * @author Sun Dasheng
 */
@Slf4j
public class DoubleMappBuffer {

    private NameNodeConfig nameNodeConfig;
    private EditLogMappBuffer currentBuffer;
    private EditLogMappBuffer syncBuffer;

    public DoubleMappBuffer(NameNodeConfig nameNodeConfig, List<EditslogInfo> editLogInfos) {
        this.nameNodeConfig = nameNodeConfig;
        long startTxid=1;
        if (editLogInfos.size() != 0) {
            EditslogInfo editslogInfo = editLogInfos.get(editLogInfos.size() - 1);
            startTxid=editslogInfo.getEnd()+1;
//            try {
//                List<EditLogWrapper> editLogWrappers =
//                        EditLogWrapper.parseFrom(FileUtil.readBuffer(editslogInfo.getName()));
//                for (EditLogWrapper editLogWrapper : editLogWrappers) {
//                    position=Math.max(editLogWrapper.getEndPosition(),position);
//                    startTxid=Math.max(editLogWrapper.getTxId(),startTxid);
//                }
//                if (editLogWrappers.size()!=0){
//                    startTxid++;
//                }
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
        }
        EditLogMappBuffer editLogWrappers =
        this.currentBuffer = new EditLogMappBuffer(nameNodeConfig,startTxid,
                startTxid+nameNodeConfig.getDEFAULT_EDITLOG_COUNT()-1,0);
        this.syncBuffer = new EditLogMappBuffer(nameNodeConfig, startTxid + nameNodeConfig.getDEFAULT_EDITLOG_COUNT(),
                startTxid+nameNodeConfig.getDEFAULT_EDITLOG_COUNT()*2-1,0);
    }

    /**
     * 写入一条editlog
     */
    public void write(EditLogWrapper editLog) throws IOException {
        log.debug("editlog buffer写了一条日志[{}]",editLog);
        currentBuffer.write(editLog);
    }

    /**
     * 交换两块缓冲区
     */
    public void setReadyToSync() {
        EditLogMappBuffer temp = currentBuffer;
        currentBuffer = syncBuffer;
        syncBuffer = temp;
    }

    /**
     * 把缓冲区的editlog数据刷新到磁盘
     */
    public EditslogInfo flush() throws IOException {
        log.debug("缓冲区触发flush");
        EditslogInfo editslogInfo = syncBuffer.flush();
        //关闭
        syncBuffer.close();
        //生产一个新的buffer
        syncBuffer=new EditLogMappBuffer(nameNodeConfig,
                editslogInfo.getStart()+nameNodeConfig.getDEFAULT_EDITLOG_COUNT()*2,
                editslogInfo.getStart()+nameNodeConfig.getDEFAULT_EDITLOG_COUNT()*3-1,0);
        return editslogInfo;
    }

    /**
     * 是否可以刷新磁盘
     *
     * @return 是否可以刷磁盘
     */
    public boolean shouldForceSync() {
        return currentBuffer.count() >= nameNodeConfig.getDEFAULT_EDITLOG_COUNT();
    }

    public List<EditLogWrapper> getCurrentEditLog() {
        return currentBuffer.getCurrentEditLog();
    }
}
